package com.george.reversing.util;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Arrays;

import android.util.Log;

/***
 * read and write thread; RW type: file
 * 
 * @author hrains
 * 
 */
public class RWThread extends Thread {
	private final File mFile;
	private InputStream mInStream;
	private OutputStream mOutStream;
	private boolean isReady;
	private static final String TAG = RWThread.class.getName();
	private final RWThreadCallback mCallback;
	private byte[] exitCode = { 0, 0 };
	
	boolean DEBUG = true;

	public RWThread(File file, RWThreadCallback callback) {
		mFile = file;
		isReady = true;
		mCallback = callback;
		try {// create file stream
			mInStream = new FileInputStream(mFile);
			mOutStream = new FileOutputStream(mFile);
		} catch (IOException e) {
			Log.e(TAG, "temp sockets not created", e);
			mCallback.connectError();
		}
	}

	public void setReadyState(boolean ready) {
		isReady = ready;
	}

	public boolean isReady() {
		return isReady;
	}

	public void run() {
		byte[] buffer = new byte[128];
		int bytes = 0;

		if (mCallback != null && isReady) {
			mCallback.ThreadRun();
		}
		// Keep listening to the InputStream while connected
		while (isReady) {
			// Read from the InputStream
			try {
				bytes = mInStream.read(buffer);
				if (DEBUG) {
					dump(buffer, bytes);
				}
				if (buffer != null && bytes > 0 && buffer[0] != 0) {
					mCallback.parseProtocol(Arrays.copyOf(buffer, bytes), bytes);
				}
			} catch (IOException e) {
				Log.e(TAG, "disconnected", e);
			}
		}
	}

	/**
	 * Write to the connected OutStream.
	 * 
	 * @param buffer
	 *            The bytes to write
	 */
	public void write(byte[] buffer) {
		try {
			mOutStream.write(buffer);
			if (DEBUG) {
				dump(buffer, buffer.length);
			}
		} catch (IOException e) {
			Log.e(TAG, "Exception during write", e);
		}
	}

	public void cancel() {
		try {
			isReady = false;
			write(exitCode);
			mOutStream.flush();
			mInStream.close();
			mOutStream.close();
			mOutStream = null;
			mInStream = null;
		} catch (IOException e) {
			Log.e(TAG, "close() of connect socket failed", e);
		}
	}

	private void dump(byte buffer[], int length) {
		String read = "";
		for (int i = 0; i < length; i++) {
			read += String.format("%02x  ", buffer[i]);
		}
		Log.d(TAG, read);
	}
}
